package com.bird.component.sensitive

import com.bird.component.lang.util.isnull
import com.fasterxml.jackson.annotation.JsonAutoDetect
import com.fasterxml.jackson.annotation.PropertyAccessor
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
import java.time.format.DateTimeFormatter

class SensitiveLogUtil {
    companion object {
        private val DATE_FORMAT: String = "yyyy-MM-dd"
        private val DATE_TIME_FORMAT: String = "yyyy-MM-dd HH:mm:ss"
        private val TIME_FORMAT: String = "HH:mm:ss"
        val currentObjectMapper: ObjectMapper
        init {
            val jackson2ObjectMapperBuilder = Jackson2ObjectMapperBuilder()
            jackson2ObjectMapperBuilder.serializers(LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT)))
            jackson2ObjectMapperBuilder.serializers(LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)))
            jackson2ObjectMapperBuilder.serializers(LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_FORMAT)))
            jackson2ObjectMapperBuilder.deserializers(LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)))
            jackson2ObjectMapperBuilder.deserializers(LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FORMAT)))
            jackson2ObjectMapperBuilder.deserializers(LocalTimeDeserializer(DateTimeFormatter.ofPattern(TIME_FORMAT)))
            currentObjectMapper = jackson2ObjectMapperBuilder.build()
            // 反序列化时忽略不存在的字段
            currentObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            currentObjectMapper.registerKotlinModule()
            // 注册处理敏感字段的扩展模块
            currentObjectMapper.registerModule(StringSensitiveFieldProcessModule())
            currentObjectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
            currentObjectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
            currentObjectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
            currentObjectMapper.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE)
            currentObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
        }
    }
}

fun Any?.toJacksonJsonStr(): String? {
    return this.let {
        try {
            if (it.isnull()) {
                null
            }else{
                SensitiveLogUtil.currentObjectMapper.writeValueAsString(it)
            }
        }catch (e: JsonProcessingException) {
            null
        }
    }
}